package abel.wlmr.model.unit;

import java.time.DateTimeException;

import abel.util.StdBcdNumber;
import abel.wlmr.model.WlmrBaseUnit;
import abel.wlmr.model.WlmrException;
import abel.wlmr.model.type.FlowPointC29Body;
import abel.wlmr.model.type.VolumeUnitField;
import io.netty.buffer.ByteBuf;

/**
 * B.5.11.2.4.71 F410：水表月冻结正向累积流量示值
 * 数据单元格式见表 B.171。
 * 表B.171 月冻结正向累积流量示值数据单元格式
 * 数据内容 数据格式 单位 字节数
 * 月冻结类数据时标 Td_m 见本附录 B.5.13.1.3.5 月年 2
 * 终端抄表时间 见附录 C.15 分时日月年 5
 * 正向总流量示值 见附录 C.29 单位代号 5
 * 
 * @author Abel
 *
 */
public class AfnSecondF410Unit extends WlmrBaseUnit {
    private static final short FIXED_LENGTH = 2 + 5 + 5;

    /**
     * B.5.11.1.3.5 日月冻结类数据时标Td_m
     * 月冻结类数据时标 Td_m 的长度为 2 个字节，定义见表 B.120。
     * 表B.120 日月冻结类数据时标数据单元格式
     * 数据内容 数据格式 字节数
     * 月年 见附录 C.21 2
     * 月冻结数据是指终端在每月月末 24 点时刻所冻结的数据，其中由抄表得到的数据是月末 24 点时刻
     * 所抄回冻结的远传表数据。
     */
    private StdBcdNumber frozeTdm;

    /**
     * 终端抄表时间 见附录 C.15 分时日月年 5
     */
    private StdBcdNumber readingTime;

    /**
     * 正向总流量示值 见附录 C.29 单位代号 5
     */
    private FlowPointC29Body<VolumeUnitField> forwardFLow =
            new FlowPointC29Body<VolumeUnitField>(new VolumeUnitField());

    public AfnSecondF410Unit() {
        super();
    }

    public AfnSecondF410Unit(short guessedLen) {
        super(guessedLen);
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#appendBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public ByteBuf appendBuf(ByteBuf buf) {
        if (frozeTdm == null || frozeTdm.length() != 2) {
            throw new IllegalArgumentException("froze tdm should be 2 bcd long");
        }
        if (readingTime == null || readingTime.length() != 5) {
            throw new IllegalArgumentException("reading time should be 5 bcd long");
        }
        if (forwardFLow == null) {
            throw new IllegalArgumentException("forward flow can't be null");
        }

        buf.writeBytes(frozeTdm.toBytes());
        buf.writeBytes(readingTime.toBytes());
        forwardFLow.appendBuf(buf);

        return buf;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#parseBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public int parseBuf(ByteBuf buf) throws WlmrException {
        if (checkBuffer(buf) < 0) {
            return -1;
        }

        frozeTdm = new StdBcdNumber();
        frozeTdm.populateBytes(buf, 2);

        try {
            frozeTdm.toMeterC21Joda();
        } catch (DateTimeException e) {
            throw new WlmrException("invalid froze-tdd in C.21", e);
        }

        readingTime = new StdBcdNumber();
        readingTime.populateBytes(buf, 5);

        try {
            readingTime.toMeterC15Joda();
        } catch (DateTimeException e) {
            throw new WlmrException("invalid reading time in C.15", e);
        }

        forwardFLow.parseBuf(buf);

        return FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.WlmrDataPart#getMinLength()
     */
    @Override
    public int getMinLength() {
        return FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#getFinalLen()
     */
    @Override
    public short getFinalLen() {
        return FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return String.format("{frozeTdm:%s, readingTime:%s, forwardFLow:%s}", frozeTdm, readingTime, forwardFLow);
    }

    /**
     * B.5.11.1.3.5 日月冻结类数据时标Td_m
     * 月冻结类数据时标 Td_m 的长度为 2 个字节，定义见表 B.120。
     * 表B.120 日月冻结类数据时标数据单元格式
     * 数据内容 数据格式 字节数
     * 月年 见附录 C.21 2
     * 月冻结数据是指终端在每月月末 24 点时刻所冻结的数据，其中由抄表得到的数据是月末 24 点时刻
     * 所抄回冻结的远传表数据。
     * 
     * @return the frozeTdm
     */
    public StdBcdNumber getFrozeTdm() {
        return frozeTdm;
    }

    /**
     * B.5.11.1.3.5 日月冻结类数据时标Td_m
     * 月冻结类数据时标 Td_m 的长度为 2 个字节，定义见表 B.120。
     * 表B.120 日月冻结类数据时标数据单元格式
     * 数据内容 数据格式 字节数
     * 月年 见附录 C.21 2
     * 月冻结数据是指终端在每月月末 24 点时刻所冻结的数据，其中由抄表得到的数据是月末 24 点时刻
     * 所抄回冻结的远传表数据。
     * 
     * @param frozeTdm
     *            the frozeTdm to set
     */
    public void setFrozeTdm(StdBcdNumber frozeTdm) {
        if (frozeTdm == null || frozeTdm.length() != 2) {
            throw new IllegalArgumentException("froze tdm should be 2 bcd long");
        }

        this.frozeTdm = frozeTdm;
    }

    /**
     * 终端抄表时间 见附录 C.15 分时日月年 5
     * 
     * @return the readingTime
     */
    public StdBcdNumber getReadingTime() {
        return readingTime;
    }

    /**
     * 终端抄表时间 见附录 C.15 分时日月年 5
     * 
     * @param readingTime
     *            the readingTime to set
     */
    public void setReadingTime(StdBcdNumber readingTime) {
        if (readingTime == null || readingTime.length() != 5) {
            throw new IllegalArgumentException("reading time should be 5 bcd long");
        }

        this.readingTime = readingTime;
    }

    /**
     * 正向总流量示值 见附录 C.29 单位代号 5
     * 
     * @return the forwardFLow
     */
    public FlowPointC29Body<VolumeUnitField> getForwardFLow() {
        return forwardFLow;
    }

    /**
     * 正向总流量示值 见附录 C.29 单位代号 5
     * 
     * @param forwardFLow
     *            the forwardFLow to set
     */
    public void setForwardFLow(FlowPointC29Body<VolumeUnitField> forwardFLow) {
        if (forwardFLow == null) {
            throw new IllegalArgumentException("forward flow can't be null");
        }

        this.forwardFLow = forwardFLow;
    }
}
